package com.ruicar.afs.cloud.manage.common.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruicar.afs.cloud.basic.api.corporate.fegin.CorporateTransferFeign;
import com.ruicar.afs.cloud.basic.api.dto.UpdateBankCardInfoDto;
import com.ruicar.afs.cloud.bizcommon.cms.dto.CmsResponse;
import com.ruicar.afs.cloud.bizcommon.cms.enums.CodeResponseEnum;
import com.ruicar.afs.cloud.bizcommon.cms.enums.SuccessResponseEnum;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.security.util.SecurityUtils;
import com.ruicar.afs.cloud.common.core.translog.service.GlobalTransService;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.enums.ServiceNameEnum;
import com.ruicar.afs.cloud.common.enums.ToBasicSyncDataUrl;
import com.ruicar.afs.cloud.common.modules.contract.enums.*;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import com.ruicar.afs.cloud.manage.cms.service.IcosToCmsChangeRepaymentService;
import com.ruicar.afs.cloud.manage.common.entity.ComAttachementFile;
import com.ruicar.afs.cloud.manage.common.entity.ManageApplyRecord;
import com.ruicar.afs.cloud.manage.common.entity.ManageBankCardChange;
import com.ruicar.afs.cloud.manage.common.mapper.ManageBankCardChangeMapper;
import com.ruicar.afs.cloud.manage.common.service.ComAttachementFileService;
import com.ruicar.afs.cloud.manage.common.service.ManageApplyRecordService;
import com.ruicar.afs.cloud.manage.common.service.ManageBankCardChangeService;
import com.ruicar.afs.cloud.manage.common.util.CreatCaseNoUtil;
import com.ruicar.afs.cloud.manage.creditchange.condition.BankCardChangeCondition;
import com.ruicar.afs.cloud.manage.creditchange.enums.BankTemplateIdEnum;
import com.ruicar.afs.cloud.manage.creditchange.vo.BankApprovalVo;
import com.ruicar.afs.cloud.manage.creditchange.vo.BankCardChangeToCmsVO;
import com.ruicar.afs.cloud.manage.creditchange.vo.BankCardManageVO;
import com.ruicar.afs.cloud.manage.workflow.enums.NormalSubmitEnum;
import com.ruicar.afs.cloud.manage.workflow.enums.WorkflowTypeEnum;
import com.ruicar.afs.cloud.manage.workflow.processor.ContractWorkFlowSaveApproveInfoProcessor;
import com.ruicar.afs.cloud.manage.workflow.service.WorkflowSubmitService;
import com.ruicar.afs.cloud.manage.workflow.vo.TaskSubmitVO;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.request.StartFlowRequest;
import com.ruicar.afs.cloud.workflow.gwt.service.WorkflowService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * @author: Lee
 * @date 2020-05-30 04:45:15
 * @description
 */
@Service
@AllArgsConstructor
public class ManageBankCardChangeServiceImpl extends ServiceImpl<ManageBankCardChangeMapper, ManageBankCardChange> implements ManageBankCardChangeService {

    private final ContractWorkFlowSaveApproveInfoProcessor saveApproveInfoProcessor;
    private final WorkflowSubmitService workflowSubmitService;
    private final ComAttachementFileService comAttachementFileService;
    private final WorkflowService workflowService;
    private final GlobalTransService globalTransService;
    private final CorporateTransferFeign bankFeignService;
    private final ManageApplyRecordService manageApplyRecordService;
    private final IcosToCmsChangeRepaymentService icosToCmsChangeRepaymentService;

    @Override
    public ManageBankCardChange saveBankCardRecord(BankCardManageVO bankvo) {

        ManageBankCardChange bankCardChange = baseMapper.selectOne(Wrappers.<ManageBankCardChange>query().lambda()
                .eq(ManageBankCardChange::getContractNo, bankvo.getContractNo())
                .notIn(ManageBankCardChange::getProcessStatus, ProcessStatusEnum.approved, ProcessStatusEnum.refuse));
        /**因为联动身份信息变更，应客户要求，取消此校验*/
        //银行卡校验
        if (bankvo.getNewBank() != null && bankvo.getNewBankAccount() != null &&
                bankvo.getNewBank().equals(bankvo.getOldBank())
                && bankvo.getNewBankAccount().equals(bankvo.getOldBankAccount())) {
            throw new AfsBaseException(CommonConstants.FAIL, "同银行同卡号不能提交");
        }
        //保存信息
        if (bankCardChange == null) {
            bankvo.setId(null);
            bankvo.setCaseNo(null);
            // 生成案件编号
            bankvo.setCaseNo(CreatCaseNoUtil.GeneratorCaseNo(ContractBusinessEnum.bankCardChange));
            //更改状态
            bankvo.setCloseDate(bankvo.getCloseDate());//合同关闭时间
            bankvo.setProcessStatus(ProcessStatusEnum.draft);
            bankvo.setApplyDate(new Date());
            bankvo.setCustName(bankvo.getCustName());
            bankvo.setProvince(bankvo.getNewProvince());
            bankvo.setCity(bankvo.getNewCity());
            //应客户需求，当经销商申请时，创建人显示申请人名字+电话,   申请人为业务人员是，只显示名字
            //TODO CK 1、目前仅有姓名，需要从进件获取手机号
            String role = SecurityUtils.getRoles().get(0);//经销商或业务员身份
            if (role.equals(BusinessSourceEnum.SP)) {
                bankvo.setApplyBy(SecurityUtils.getUser().getUserRealName());
//                bankvo.setCreateBy(SecurityUtils.getUser().getUsername());
            } else {
                bankvo.setApplyBy(SecurityUtils.getUser().getUserRealName());
//                bankvo.setCreateBy(SecurityUtils.getUser().getUsername());
            }
            save(bankvo);
        } else {
            if (!ProcessStatusEnum.draft.equals(bankCardChange.getProcessStatus())
                    && !ProcessStatusEnum.toBeRepaired.equals(bankCardChange.getProcessStatus())
                    && !ProcessStatusEnum.approved.equals(bankCardChange.getProcessStatus())
                    && !ProcessStatusEnum.refuse.equals(bankCardChange.getProcessStatus())) {
                throw new AfsBaseException(CommonConstants.FAIL, "此合同编号已流程中！");
            }
            bankvo.setProvince(bankvo.getNewProvince());
            bankvo.setCity(bankvo.getNewCity());
            bankvo.setCustName(bankvo.getCustName());

            baseMapper.updateById(bankvo);

        }

        bankCardChange = baseMapper.selectOne(Wrappers.<ManageBankCardChange>query().lambda()
                .eq(ManageBankCardChange::getContractNo, bankvo.getContractNo())
                .notIn(ManageBankCardChange::getProcessStatus, ProcessStatusEnum.approved, ProcessStatusEnum.refuse));
        //将保存的图片的busiNo换成caseNo
        comAttachementFileService.saveFile(bankCardChange.getContractNo(), bankCardChange.getCaseNo(), AttachmentTypeEnum.bankCard.name());
        BeanUtils.copyProperties(bankCardChange, bankvo);
        return bankvo;
    }

    @Override
    public void submitBankCardRecord(BankCardManageVO bankvo) {
        Object [] custRole = bankvo.getCustRoleData();
        ManageBankCardChange cardChange = new ManageBankCardChange();
        if (StringUtils.isNotEmpty(bankvo.getCertNo()) && !bankvo.getCertNo().equals(bankvo.getOldCertNo())){
            throw new AfsBaseException("所填证件号与个人信息绑定证件号不一致，请重新填写");
        }
        if (bankvo.getCaseNo() != null) {
            cardChange = baseMapper.selectOne(Wrappers.<ManageBankCardChange>lambdaQuery()
                    .eq(ManageBankCardChange::getCaseNo, bankvo.getCaseNo()));
        } else {
            cardChange = baseMapper.selectById(bankvo.getId());
        }
        if (StringUtils.isEmpty(cardChange.getNewCardholder())) {
            throw new AfsBaseException("持卡人（新）未填写");
        }
        if (StringUtils.isEmpty(cardChange.getNewBankAccount())) {
            throw new AfsBaseException("银行账号（新）未填写");
        }
        if (StringUtils.isEmpty(cardChange.getNewBank())) {
            throw new AfsBaseException("还款银行（新）未填写");
        }
        if (StringUtils.isEmpty(cardChange.getProvince()) || StringUtils.isEmpty(cardChange.getCity())) {
            throw new AfsBaseException("分支行（新）未填写");
        }
        if (EmptyUtils.isEmpty(cardChange.getCertEndDate())) {
            throw new AfsBaseException("有效期为空");
        }
        if (cardChange.getCertEndDate() != null) {
            certDateCheck(bankvo.getCertEndDate(), bankvo.getIdCardDays());
        }
        if (bankvo.getCertNo() != null) {
            if (((bankvo.getNewCardholder().equals(((LinkedHashMap) custRole[0]).get("custName")))
                    && (!bankvo.getCertNo().equals(((LinkedHashMap) custRole[0]).get("certNo"))))
                    || ((bankvo.getNewCardholder().equals(((LinkedHashMap) custRole[1]).get("custName"))
                    && (!bankvo.getCertNo().equals(((LinkedHashMap) custRole[1]).get("certNo")))))) {
                throw new AfsBaseException("所填证件号与个人信息绑定证件号不一致，请重试");
            }
        }
        BeanUtils.copyProperties(cardChange, bankvo);
        bankvo.setProvince(bankvo.getNewProvince());
        bankvo.setCity(bankvo.getNewCity());
        if (bankvo.getId() == null) {
            //先进行保存之后，才能提交
            throw new AfsBaseException(CommonConstants.FAIL, "合同业务信息请保存！");
        }
        ManageBankCardChange bankCardChange = baseMapper.selectOne(Wrappers.<ManageBankCardChange>lambdaQuery()
                .eq(ManageBankCardChange::getContractNo, bankvo.getContractNo())
                .notIn(ManageBankCardChange::getProcessStatus, ProcessStatusEnum.approved, ProcessStatusEnum.refuse));
        bankvo.setCaseNo(bankCardChange.getCaseNo());
        bankvo.setCustName(bankCardChange.getCustName());
        //校验 同银行同卡号不能提交
        if (bankvo.getNewBank() == bankvo.getOldBank() && bankvo.getNewBankAccount() == bankvo.getOldBankAccount()) {
            throw new AfsBaseException(CommonConstants.FAIL, "同银行同卡号不能提交");
        }
        //提交前，身份证，银行卡照片校验
        ManageBankCardChange bankCardInfo = baseMapper.selectById(bankvo.getId());
        String[] bankCardFile = new String[2];
        bankCardFile[0] = BankTemplateIdEnum.BankChangeBankCardFrontCode.getDesc();
        bankCardFile[1] = BankTemplateIdEnum.BankChangeBankCardBackCode.getDesc();
        String[] idCardFile = new String[2];
        idCardFile[0] = BankTemplateIdEnum.BankChangeIdCardFrontCode.getDesc();
        idCardFile[1] = BankTemplateIdEnum.BankChangeIdCardBackCode.getDesc();
        List<ComAttachementFile> custPhoto = comAttachementFileService.list(Wrappers.<ComAttachementFile>lambdaQuery()
                .eq(ComAttachementFile::getBusiNo, bankCardInfo.getCaseNo())
                .in(ComAttachementFile::getAttachmentCode, idCardFile));
        List<ComAttachementFile> bankPhoto = comAttachementFileService.list(Wrappers.<ComAttachementFile>lambdaQuery()
                .eq(ComAttachementFile::getBusiNo, bankCardInfo.getCaseNo())
                .in(ComAttachementFile::getAttachmentCode, bankCardFile));
        List<ComAttachementFile> bankFile = comAttachementFileService.list(Wrappers.<ComAttachementFile>lambdaQuery()
                .eq(ComAttachementFile::getBusiNo, bankCardInfo.getCaseNo())
                .eq(ComAttachementFile::getAttachmentCode, "4588631527359512579"));
        if (custPhoto.size() < 2) {
            throw new AfsBaseException("身份证正反照不全");
        }
        if (bankPhoto.size() < 2) {
            throw new AfsBaseException("银行卡正反照不全");
        }
        if (bankFile.size() < 1) {
            throw new AfsBaseException("授权书未上传");
        }
        //提交审核，发起流程
        if (ProcessStatusEnum.draft.equals(bankvo.getProcessStatus())) {
            //线下签约
            bankvo.setProcessStatus(ProcessStatusEnum.underReview);
            updateById(bankvo);
            //保存合同信息变更申请记录
            //保存待办任务记录
            saveApproveInfoProcessor.saveApproveRecord(bankvo, ContractBusinessEnum.bankCardChange);
            saveApproveInfoProcessor.saveApproveInfo(bankvo, ContractBusinessEnum.bankCardChange,
                    CaseStatusEnum.UNDER_REVIEW, BusinessUrlEnum.BANK_CHANGE);

            ManageApplyRecord applyRecord = manageApplyRecordService.getOne(Wrappers.<ManageApplyRecord>lambdaQuery()
                    .eq(ManageApplyRecord::getCaseNo, bankvo.getCaseNo()));
            applyRecord.setBusinessSource(bankvo.getBusinessSource());


            StartFlowRequest startFlowRequest = new StartFlowRequest();
            startFlowRequest.setAfsFlowKey(AfsEnumUtil.key(WorkflowTypeEnum.BANK_CHANGE));
            startFlowRequest.setBizDataId(String.valueOf(bankvo.getId()));
            startFlowRequest.setFlowName((StringUtils.isEmpty(bankvo.getAccountName()) ? "" : (bankvo.getAccountName()) + "-") + AfsEnumUtil.desc(WorkflowTypeEnum.BANK_CHANGE));
            String json = JSONObject.toJSONString(bankvo);
            JSONObject cancelJson = JSONObject.parseObject(json);
            workflowService.startWorkFlow(startFlowRequest, cancelJson);
//            }
        }

    }

    @Override
    public void saveProposalApplicationInfo(BankApprovalVo bankvos) {
        Boolean flag = false;
        for (BankCardManageVO bankvo : bankvos.getBankCardManageVOs()) {
            if (bankvo.getApprovalOperating() == null) {
                bankvo.setApprovalOperating(bankvos.getApprovalOperating());
                bankvo.setApprovalOpinion(bankvos.getApprovalOpinion());
            }
            bankvo.setCity(bankvo.getNewCity());
            bankvo.setProvince(bankvo.getNewProvince());
            CaseStatusEnum CaseStatus;
            ProcessStatusEnum processStatus;

            //流程审批
            TaskSubmitVO vo = new TaskSubmitVO();
            String json = JSONObject.toJSONString(bankvo);
            JSONObject cancelJson = JSONObject.parseObject(json);
            vo.setBizData(cancelJson);
            vo.setApprovalOperating(bankvo.getApprovalOperating());
            vo.setApprovalOpinion(bankvo.getApprovalOpinion());
            vo.setReasonType(bankvo.getReasonType());
            workflowSubmitService.submit(vo);

            //更新处理状态
            if (AfsEnumUtil.key(NormalSubmitEnum.SUGGEST_CHECK_FINAL).equals(bankvo.getApprovalOperating())) {
                //结束节点直接完成
                if (bankvo.getProcessStatus().equals(ProcessStatusEnum.submission)) {
                    bankvo.setEndDate(DateUtil.date());
                    flag = true;
                    CaseStatus = CaseStatusEnum.APPROVED;
                    processStatus = ProcessStatusEnum.approved;
                } //报送节点时状态变为报送
                else if (bankvo.getProcessStatus().equals(ProcessStatusEnum.noSubmission)) {
                    CaseStatus = CaseStatusEnum.SUBMISSION;
                    processStatus = ProcessStatusEnum.submission;
                }//否则改为未报送状态
                else {
                    CaseStatus = CaseStatusEnum.NO_SUBMISSION;
                    processStatus = ProcessStatusEnum.noSubmission;
                }
                bankvo.setProcessStatus(processStatus);
                //保存待办任务记录
                //保存合同信息变更申请记录
                saveApproveInfoProcessor.saveApproveInfo(bankvo, ContractBusinessEnum.bankCardChange,
                        CaseStatus, BusinessUrlEnum.BANK_CHANGE);
            } else if (AfsEnumUtil.key(NormalSubmitEnum.SUGGEST_REJECT_FINAL).equals(bankvo.getApprovalOperating())) {

                bankvo.setEndDate(DateUtil.date());
                CaseStatus = CaseStatusEnum.REFUSE;
                bankvo.setProcessStatus(ProcessStatusEnum.refuse);
                //保存合同信息变更申请记录
                //保存待办任务记录
                saveApproveInfoProcessor.saveApproveInfo(bankvo, ContractBusinessEnum.bankCardChange,
                        CaseStatus, BusinessUrlEnum.BANK_CHANGE);
            }
            /**客户流程变更，无退回业务*/
//            } else if (AfsEnumUtil.key(NormalSubmitEnum.SEND_BACK).equals(bankvo.getApprovalOperating())) {
//                WorkTaskCreatedInfo workTaskCreatedInfo = workTaskCreatedInfoService.getOne(Wrappers.<WorkTaskCreatedInfo>query().lambda()
//                                .eq(WorkTaskCreatedInfo::getBizDataId, bankvo.getId())
//                                .orderByDesc(WorkTaskCreatedInfo::getCreateTime)
//                        , false
//                );
//                if ((workTaskCreatedInfo.getTaskMemo()).equals("preliminary")) {
//                    bankvo.setProcessStatus(ProcessStatusEnum.toBeRepaired);
//                } else {
//                    bankvo.setProcessStatus(ProcessStatusEnum.underReview);
//                }
//                //保存待办任务记录
//                saveApproveInfoProcessor.saveApproveInfo(bankvo, ContractBusinessEnum.bankCardChange,
//                        CaseStatusEnum.UNDER_REVIEW, BusinessUrlEnum.BANK_CHANGE);
//            }
            updateById(bankvo);
            //审批后数据更新
            if (flag) {
                updateBankInfo(bankvo);
            }
        }
        List<ManageApplyRecord> one = manageApplyRecordService.list(Wrappers.<ManageApplyRecord>lambdaQuery()
                .eq(ManageApplyRecord::getCaseNo, null));
        manageApplyRecordService.remove(Wrappers.<ManageApplyRecord>lambdaQuery()
                .eq(ManageApplyRecord::getCaseNo, null));
    }

    @Override
    public IPage getManageBankCardChangeList(Page page, BankCardChangeCondition condition) {
        return baseMapper.getManageBankCardChangeList(page, condition);
    }

    /**
     * 更新银行卡信息
     *
     * @param bankVO
     */
    public void updateBankInfo(BankCardManageVO bankVO) {
        UpdateBankCardInfoDto dto = new UpdateBankCardInfoDto();
        //银行卡信息
        dto.setContractNo(bankVO.getContractNo());
        dto.setNewBank(bankVO.getNewBank());
        dto.setNewBranchBank(bankVO.getNewBranchBank());
        dto.setNewCardholder(bankVO.getNewCardholder());
        dto.setNewBankAccount(bankVO.getNewBankAccount());
        dto.setProvince(bankVO.getProvince());
        dto.setCity(bankVO.getCity());
        //持卡人信息
        dto.setCertNo(bankVO.getCertNo());
        dto.setCustName(bankVO.getCustName());
        bankFeignService.updateBankInfo(dto);

        ManageBankCardChange bankCardInfo = baseMapper.selectById(bankVO);
        //向basic同步结果
        if (DataSourceEnum.icos == bankCardInfo.getDataSource()) {
            BankCardChangeToCmsVO vo = new BankCardChangeToCmsVO();
            vo.setAccountName(bankCardInfo.getNewCardholder());
            vo.setAccountNo(bankCardInfo.getNewBankAccount());
            vo.setApplicationNo(bankCardInfo.getApplyNo());
            vo.setApprover(bankCardInfo.getCreateBy());
            vo.setBank(bankCardInfo.getNewBank());
            vo.setBranch("103");
            vo.setOperatorUser(bankCardInfo.getUpdateBy());
            vo.setOrigin("icos");
            vo.setRequestId(String.valueOf(bankCardInfo.getId()));
            IResponse<Boolean> response = globalTransService.post(String.valueOf(bankCardInfo.getId()), AfsEnumUtil.key(ServiceNameEnum.BASIC), AfsEnumUtil.key(ToBasicSyncDataUrl.SYNC_CHANGE_BANKCARD_DATA), vo, new TypeReference<Boolean>() {
            });
            if (CommonConstants.FAIL.equals(response.getCode())) {
                throw new AfsBaseException("银行卡变更结果数据推送至basic服务失败，请重试！");
            }
        } else {
            CmsResponse response = icosToCmsChangeRepaymentService.syncToCmsChangeBankCardResult(bankCardInfo);
            if (AfsEnumUtil.key(SuccessResponseEnum.FAIL).equals(response.getSuccess()) && !AfsEnumUtil.key(CodeResponseEnum.M10051).equals(response.getCode())) {
                throw new AfsBaseException("银行卡变更结果数据推送至cms系统失败，请重试！");
            }
        }
    }

    /**
     * 证件信息验证
     */
    private boolean certDateCheck(Date endDate, String idCardDays) {
        Boolean valid = false;
        Date now = new Date();
        Long days = (endDate.getTime() - now.getTime()) / (24 * 60 * 60 * 1000);
        Long time = new Long(idCardDays);
        if (days.longValue() <=0) { //身份证有效期大于当前时间20天
            throw new AfsBaseException("您的身份证已过期，请使用有效身份证申请");
        }else if(days.longValue() < time.longValue()){
            throw new AfsBaseException("您的身份证即将过期，请更换后申请");
        }

        /**客户需求变更，不要求显示起始日期*/
            /*String smon = String.format("%tm", sdfStartDate);
            String sday = String.format("%td", sdfStartDate);

            String emon = String.format("%tm", sdfEndDate);
            String eday = String.format("%td", sdfEndDate);
            //身份证有效期的月份，日期一致校验/0
            if ((!smon.equals(emon)) || (!sday.equals(eday))) {
                throw new AfsBaseException("证件起止的月份日期不一致");
            }*/
        return valid;
    }

    /**
     * 时间格式转换
     */
    private Date formatDateTime(Date date) {
        Date dateTime = null;
        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dateString = sdf.format(date);
        try {
            Date dateParse = sdf.parse(dateString);
            java.sql.Date resultStDate = new java.sql.Date(dateParse.getTime());
            dateTime = resultStDate;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return dateTime;
    }
}
